package net;

import net.message.*;
import net.sending.SendingMessage;
import static net.Synchronizer.ImageWrapper;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.Set;
import java.util.HashSet;
import java.awt.*;

import util.Config;

public class Sender extends StoppableWorker {

    private final SendingMessageFactory factory;

    private final BlockingQueue<SendingMessage> messages = new LinkedBlockingQueue<SendingMessage>();

    private final String clientName;

    public Sender(SendingMessageFactory factory) {
        this.clientName = Config.getInstance().getName();
        this.factory = factory;
    }

    public void sendAlive() {
        putBroadcastMessage(new AliveMessage());
    }

    public void sendHelloRequest() {
        putBroadcastMessage(new HelloRequestMessage(clientName));
    }

    public void sendGetImageRequest(ImageWrapper iw, HashSet<Client> clients) {
        putMulticastMessage(new GetImageRequestMessage(iw), clients);
    }

    public void sendCreateImage(int imageID) {
        putBroadcastMessage(new CreateImageMessage(imageID));
    }

    public void sendGetImageResponse(int[] image, int imageID, Client client) {
        putUnicastMessage(new GetImageResponseMessage(image, imageID), client);
    }

    public void sendHelloResponse(Client client, Set<Integer> imageIDs) {
        putUnicastMessage(new HelloResponseMessage(imageIDs), client);
    }

    public void sendJoinImageRequest(int imageID, HashSet<Client> clients) {
        putMulticastMessage(new JoinImageRequestMessage(imageID), clients);
    }

    public void sendJoinImageResponse(Client client, int imageID) {
        putUnicastMessage(new JoinImageResponseMessage(imageID), client);
    }

    public void sendNewLine(int imageID, HashSet<Client> clients, int x, int y, int dx, int dy, Color color) {
        putMulticastMessage(new NewLineMessage(x, y, dx, dy, color, imageID), clients);
    }


    //---------------------------------------------------------//


    @Override
    public void work() {
        try {
            messages.take().send();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }


    private void putBroadcastMessage(Message m) {
        try {
            System.out.println("Broadcast: " + m.getType());
            messages.put(factory.getSendingMessage(m));
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    private void putUnicastMessage(Message m, Client client) {
        try {
            System.out.println("Unicast: " + m.getType() + " for " + client.getName());
            messages.put(factory.getSendingMessage(m, client));
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    private void putMulticastMessage(Message m, HashSet<Client> clients) {
        try {
            System.out.println("Multicast: " + m.getType() + " for " + clients.toString());
            messages.put(factory.getSendingMessage(m, clients));
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

}